<?php
// +-------------------------------------------------------------------------------
// | DingZone [ A Rapid Development Framework For Dingtalk ]
// +-------------------------------------------------------------------------------
// | 钉钉API权限验证类 v1.0
// |
// | Copyright (c) 2014-2018 http://www.heimalanshi.com All rights reserved.
// | Author : Jie
// | Date : 2018-08-09
// +-------------------------------------------------------------------------------

namespace ding;

use app\core\model\EnterpriseModuleApi;

/**
 * 钉钉api权限校验器
 *
 * @package ding
 */
class ApiAuthHelper {
    /**
     * 企业id
     * @var
     */
    private $eid;
    /**
     * 模块id
     * @var
     */
    private $mid;
    /**
     * 企业模块api设置
     * @var
     */
    private $enterpriseModuleApis;

    /**
     * 构造函数
     *
     * @param $eid
     * @param $mid
     */
    public function __construct($eid, $mid) {
        $this->eid = $eid;
        $this->mid = $mid;
    }

    /**
     * 检测该api是否可用
     *
     * @param $apiName
     * @return bool
     * @throws \think\exception\DbException
     */
    public function auth($apiName) {
        $enterpriseModuleApis = $this->getEnterpriseModuleApis();
        if (!isset($enterpriseModuleApis[$apiName])) {
            return false;
        }
        return $enterpriseModuleApis[$apiName]['status'] == 'allow';
    }

    /**
     * 处理数据中的敏感字段
     *
     * @param $apiName
     * @param $entity
     * @return mixed
     * @throws \think\exception\DbException
     */
    public function handlePrivacy($apiName, &$entity) {
        if (!isset(ApiHelper::$apis[$apiName]) || !isset(ApiHelper::$apis[$apiName]['privacySupportFields']) || empty(ApiHelper::$apis[$apiName]['privacySupportFields'])) {
            // 如果当前api没有对应可以设置隐私策略的字段，则无需处理
            return $entity;
        }

        // 获取企业当前模块的api配置
        $enterpriseModuleApis = $this->getEnterpriseModuleApis();
        if (!isset($enterpriseModuleApis[$apiName]) || $enterpriseModuleApis[$apiName]['status'] != 'allow') {
            // 如果没有配置，则说明接口无权限，将内容重置
            unset($entity);
            $entity = [
                'errcode' => 777777,
                'errmsg' => 'api auth faied.'
            ];
            return $entity;
        }

        // 授权访问的字段
        $grantFields = $enterpriseModuleApis[$apiName]['grant_fields'];
        if (empty($grantFields)) {
            // 如果没有设置$grantFields字段，则不进行限制
            return $entity;
        }
        $grantFields = explode(',', $grantFields);
        if (empty($grantFields)) {
            return $entity;
        }

        // 如果设置了隐私字段，则只有在授权字段内的字段才可以被访问
        $privacySupportFields = ApiHelper::$apis[$apiName]['privacySupportFields'];
        $privacyDenyFields = [];
        foreach ($privacySupportFields as $filedName => $privacySupportField) {
            if (in_array($filedName, $grantFields)) {
                continue;
            }
            $privacyDenyFields[] = $filedName;
        }

        foreach ($privacyDenyFields as $privacyDenyField) {
            $entity = $this->unsetPrivacyDenyField($entity, $privacyDenyField);
        }

        return $entity;
    }

    /**
     * 处理隐私字段
     *
     * @param $entity
     * @param $privacyDenyField
     * @return mixed
     */
    public function unsetPrivacyDenyField(&$entity, $privacyDenyField) {
        if (empty($entity) || empty($privacyDenyField)) {
            return $entity;
        }

        $dotIdx = strpos($privacyDenyField, ".");
        if ($dotIdx === FALSE) {
            // 只有一层
            $fieldName = $privacyDenyField;
            $subFieldName = false;
        } else {
            $fieldName = substr($privacyDenyField, 0, $dotIdx);
            $subFieldName = substr($privacyDenyField, $dotIdx + 1);
        }

        if (!isset($entity[$fieldName])) {
            return $entity;
        }

        if (empty($subFieldName)) {
            // 只有一层
            unset($entity[$fieldName]);
            return $entity;
        }

        // 多层，逐层向下处理
        if (is_array($entity[$fieldName])) {
            $fieldValueArray = [];
            foreach ($entity[$fieldName] as &$fieldValueItem) {
                $fieldValueItem = $this->unsetPrivacyDenyField($fieldValueItem, $subFieldName);
                $fieldValueArray[] = $fieldValueItem;
            }
            $entity[$fieldName] = $fieldValueArray;
        } else {
            $entity[$fieldName] = $this->unsetPrivacyDenyField($entity[$fieldName], $subFieldName);
        }
        return $entity;
    }

    /**
     * 获取企业模块api配置
     *
     * @throws \think\exception\DbException
     */
    private function getEnterpriseModuleApis() {
        if (empty($this->enterpriseModuleApis)) {
            $this->enterpriseModuleApis = EnterpriseModuleApi::getAll($this->eid, $this->mid);
        }
        return $this->enterpriseModuleApis;
    }

}